﻿using ArcShapeFile;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Teigha.DatabaseServices;
using Teigha.Geometry;

namespace Com.OpenCode.DwgConvert.Model
{
    /// <summary>
    /// shp文件工具类
    /// </summary>
    public static class ShapeFileUtils
    {
        /// <summary>
        /// 创建shp文件
        /// </summary>
        /// <param name="path">shp文件存储的路径</param>
        /// <param name="name">shp文件名称带后缀名</param>
        /// <param name="type">文件类型</param>
        /// <returns>返回ShapeFiles对象，可以直接继续操作</returns>
        public static ShapeFile CreateShpFile(string path, string name, eShapeType type)
        {
            string pointShp = Path.Combine(path, name);
            ShapeFile shapeFiles = new ShapeFile();
            shapeFiles.Open(pointShp, type);
            shapeFiles.Language = eLanguage.Codepage_UTF_8;
            return shapeFiles;
        }

        /// <summary>
        /// 创建shp文件
        /// </summary>
        /// <param name="path">shp文件存储的路径全名称</param>
        /// <param name="type">文件类型</param>
        /// <returns>返回ShapeFiles对象，可以直接继续操作</returns>
        public static ShapeFile CreateShpFile(string filePath, eShapeType type)
        {
            ShapeFile shapeFiles = new ShapeFile();
            shapeFiles.Language = eLanguage.Codepage_UTF_8;
            shapeFiles.Open(filePath, type);
            return shapeFiles;
        }

        /// <summary>
        /// 打开shp文件
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static ShapeFile OpenShapeFile(string filePath)
        {
            ShapeFile shapeFiles = new ShapeFile();
            shapeFiles.Language = eLanguage.Codepage_UTF_8;
            shapeFiles.Open(filePath);
            return shapeFiles;
        }

        /// <summary>
        /// 添加字段
        /// </summary>
        /// <param name="shapeFiles"></param>
        /// <param name="name"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static void AddField(ShapeFile shapeFiles, string name, eFieldType type, short size = 0, short fieldDecimal = 0)
        {
            if (shapeFiles == null)
            {
                return;
            }
            shapeFiles.Fields.Add(name, type, size, fieldDecimal);
            shapeFiles.WriteFieldDefs();
        }

        /// <summary>
        /// 添加dwg Poing到shp
        /// </summary>
        /// <param name="shapeFiles"></param>
        /// <param name="dBPoint"></param>
        public static void AddDwgPoint(ShapeFile shapeFiles, DBPoint dBPoint)
        {
            if (shapeFiles == null || dBPoint == null)
            {
                return;
            }
            shapeFiles.Vertices.Add(dBPoint.Position.X, dBPoint.Position.Y);
        }

        /// <summary>
        /// 添加dwg DBText到shp
        /// </summary>
        /// <param name="shapeFiles"></param>
        /// <param name="dBText"></param>
        public static void AddDwgText(ShapeFile shapeFiles, DBText dBText)
        {
            if (shapeFiles == null || dBText == null)
            {
                return;
            }
            shapeFiles.Vertices.Add(dBText.Position.X, dBText.Position.Y);
        }

        /// <summary>
        /// 添加dwg MText到shp
        /// </summary>
        /// <param name="shapeFiles"></param>
        /// <param name="dBText"></param>
        public static void AddDwgMText(ShapeFile shapeFiles, MText mText)
        {
            if (shapeFiles == null || mText == null)
            {
                return;
            }
            shapeFiles.Vertices.Add(mText.Location.X, mText.Location.Y);
        }

        /// <summary>
        /// 添加dwg Hatch到shp
        /// </summary>
        /// <param name="shapeFiles"></param>
        /// <param name="hatch"></param>
        public static void AddDwgHatch(ShapeFile shapeFiles, Hatch hatch)
        {
            if (shapeFiles == null || hatch == null)
            {
                return;
            }
            //shapeFiles.Vertices.AddVertice(dBText.Position.X, dBText.Position.Y);
            //shapeFiles.Fields["text"].Value = dBText.TextString;
            //shapeFiles.WriteShape();
        }

        /// <summary>
        /// 添加dwg线到shp
        /// </summary>
        /// <param name="shapeFiles"></param>
        /// <param name="line"></param>
        public static void AddDwgLine(ShapeFile shapeFiles, Line line)
        {
            if (shapeFiles == null || line == null)
            {
                return;
            }
            shapeFiles.Vertices.Add(line.StartPoint.X, line.StartPoint.Y);
            shapeFiles.Vertices.Add(line.EndPoint.X, line.EndPoint.Y);
        }

        /// <summary>
        /// 添加dwg线段到shp
        /// </summary>
        /// <param name="shapeFiles"></param>
        /// <param name="polyline"></param>
        public static void AddDwgPolyLine(ShapeFile shapeFiles, Polyline polyline)
        {
            if (shapeFiles == null || polyline == null)
            {
                return;
            }
            for (int i = 0; i < polyline.NumberOfVertices; i++)
            {
                Point2d point2D = polyline.GetPoint2dAt(i);
                shapeFiles.Vertices.Add(point2D.X, point2D.Y);
                if (i == polyline.NumberOfVertices - 1 && polyline.Closed)
                {
                    shapeFiles.Vertices.Add(polyline.GetPoint2dAt(0).X, polyline.GetPoint2dAt(0).Y);
                }
            }
        }

        /// <summary>
        /// 添加dwg polyline2D shp
        /// </summary>
        /// <param name="shapeFiles"></param>
        /// <param name="line"></param>
        public static void AddDwgPolyline2d(ShapeFile shapeFiles, Polyline2d polyline2D)
        {
            if (shapeFiles == null || polyline2D == null)
            {
                return;
            }
            Vertex2d startVertex2d = null;
            foreach (object item in polyline2D)
            {
                Vertex2d vertex2D = null;
                if (item is ObjectId)
                {
                    vertex2D = ((ObjectId)item).GetObject(OpenMode.ForRead) as Vertex2d;
                }
                else if (item is Vertex2d)
                {
                    vertex2D = item as Vertex2d;
                }
                if (startVertex2d == null)
                {
                    startVertex2d = vertex2D;
                }
                shapeFiles.Vertices.Add(vertex2D.Position.X, vertex2D.Position.Y);
            }
            if (polyline2D.Closed && startVertex2d != null)
            {
                shapeFiles.Vertices.Add(startVertex2d.Position.X, startVertex2d.Position.Y);
            }
        }

        /// <summary>
        /// 添加dwg polyline3D shp
        /// </summary>
        /// <param name="shapeFiles"></param>
        /// <param name="line"></param>
        public static void AddDwgPolyline3d(ShapeFile shapeFiles, Polyline3d polyline3D)
        {
            if (shapeFiles == null || polyline3D == null)
            {
                return;
            }
            PolylineVertex3d startPolylineVertex3d = null;
            foreach (object item in polyline3D)
            {
                PolylineVertex3d polylineVertex3D = null;
                if (item is ObjectId)
                {
                    polylineVertex3D = ((ObjectId)item).GetObject(OpenMode.ForRead) as PolylineVertex3d;
                }
                else if (item is PolylineVertex3d)
                {
                    polylineVertex3D = item as PolylineVertex3d;
                }
                if (startPolylineVertex3d == null)
                {
                    startPolylineVertex3d = polylineVertex3D;
                }
                shapeFiles.Vertices.Add(polylineVertex3D.Position.X, polylineVertex3D.Position.Y);
            }
            if (polyline3D.Closed && startPolylineVertex3d != null)
            {
                shapeFiles.Vertices.Add(startPolylineVertex3d.Position.X, startPolylineVertex3d.Position.Y);
            }
        }

        /// <summary>
        /// 添加dwg线段到shp
        /// 这里的线段必须是闭合的
        /// 闭合的线段可以转换成面对象
        /// </summary>
        /// <param name="shapeFiles"></param>
        /// <param name="polyline"></param>
        public static void AddDwgPolygon(ShapeFile shapeFiles, Polyline polyline)
        {
            if (shapeFiles == null || polyline == null || !polyline.Closed)
            {
                return;
            }
            for (int i = 0; i < polyline.NumberOfVertices; i++)
            {
                Point2d point2D = polyline.GetPoint2dAt(i);
                shapeFiles.Vertices.Add(point2D.X, point2D.Y);
                if (i == polyline.NumberOfVertices - 1)
                {
                    shapeFiles.Vertices.Add(polyline.GetPoint2dAt(0).X, polyline.GetPoint2dAt(0).Y);
                }
            }
        }

        /// <summary>
        /// 添加dwg polyline2D shp
        /// 添加到面图层
        /// 面会追加点闭合
        /// </summary>
        /// <param name="shapeFiles"></param>
        /// <param name="polyline2D"></param>
        public static void AddDwgPolygon2d(ShapeFile shapeFiles, Polyline2d polyline2D)
        {
            if (shapeFiles == null || polyline2D == null)
            {
                return;
            }
            Vertex2d startVertex2d = null;
            foreach (object item in polyline2D)
            {
                Vertex2d vertex2D = null;
                if (item is ObjectId)
                {
                    vertex2D = ((ObjectId)item).GetObject(OpenMode.ForRead) as Vertex2d;
                }
                else if (item is Vertex2d)
                {
                    vertex2D = item as Vertex2d;
                }
                if (startVertex2d == null)
                {
                    startVertex2d = vertex2D;
                }
                shapeFiles.Vertices.Add(vertex2D.Position.X, vertex2D.Position.Y);
            }
            if (startVertex2d != null)
            {
                shapeFiles.Vertices.Add(startVertex2d.Position.X, startVertex2d.Position.Y);
            }
        }

        /// <summary>
        /// 添加dwg polyline3D shp
        /// 添加到面图层
        /// 面会追加点闭合
        /// </summary>
        /// <param name="shapeFiles"></param>
        /// <param name="polyline2D"></param>
        public static void AddDwgPolygon3d(ShapeFile shapeFiles, Polyline3d polyline3D)
        {
            if (shapeFiles == null || polyline3D == null)
            {
                return;
            }
            PolylineVertex3d startPolylineVertex3d = null;
            foreach (object item in polyline3D)
            {
                PolylineVertex3d polylineVertex3D = null;
                if (item is ObjectId)
                {
                    polylineVertex3D = ((ObjectId)item).GetObject(OpenMode.ForRead) as PolylineVertex3d;
                }
                else if (item is PolylineVertex3d)
                {
                    polylineVertex3D = item as PolylineVertex3d;
                }
                if (startPolylineVertex3d == null)
                {
                    startPolylineVertex3d = polylineVertex3D;
                }
                shapeFiles.Vertices.Add(polylineVertex3D.Position.X, polylineVertex3D.Position.Y);
            }
            if (startPolylineVertex3d != null)
            {
                shapeFiles.Vertices.Add(startPolylineVertex3d.Position.X, startPolylineVertex3d.Position.Y);
            }
        }

        /// <summary>
        /// 添加dwg Circle圆形图形到shp
        /// 圆形shp需要计算边界点表示
        /// </summary>
        /// <param name="shapeFiles"></param>
        /// <param name="circle"></param>
        public static void AddDwgCircle(ShapeFile shapeFiles, Circle circle)
        {
            if (shapeFiles == null || circle == null)
            {
                return;
            }
            List<DwgPoint> simplePoints = GeometryUtils.CalcuteCirclePoints(circle.Center.X, circle.Center.Y, circle.Radius);
            foreach (DwgPoint simplePoint in simplePoints)
            {
                shapeFiles.Vertices.Add(simplePoint.X, simplePoint.Y);
            }
        }

        /// <summary>
        /// 添加dwg Arc圆形图形到shp
        /// Arc shp需要计算边界点表示
        /// </summary>
        /// <param name="shapeFiles"></param>
        /// <param name="circle"></param>
        public static void AddDwgArc(ShapeFile shapeFiles, Arc arc)
        {
            if (shapeFiles == null || arc == null)
            {
                return;
            }
            List<DwgPoint> simplePoints = GeometryUtils.CalcuteArcPoints(arc.Center.X, arc.Center.Y, arc.Radius, arc.StartAngle, arc.EndAngle);
            foreach (DwgPoint simplePoint in simplePoints)
            {
                shapeFiles.Vertices.Add(simplePoint.X, simplePoint.Y);
            }
        }

        /// <summary>
        /// 添加dwg Arc圆形图形到shp
        /// Arc shp需要计算边界点表示
        /// </summary>
        /// <param name="shapeFiles"></param>
        /// <param name="circle"></param>
        public static void AddDwgEllipse(ShapeFile shapeFiles, Ellipse ellipse)
        {
            if (shapeFiles == null || ellipse == null)
            {
                return;
            }
            List<DwgPoint> simplePoints;
            if (ellipse.Closed)
            {
                simplePoints = GeometryUtils.CalcuteEllipsePoints(ellipse.Center.X, ellipse.Center.Y, ellipse.MajorRadius, ellipse.MinorRadius, ellipse.MajorAxis.X, ellipse.MajorAxis.Y);
            }
            else
            {
                simplePoints = GeometryUtils.CalcuteEllipseArcPoints(ellipse.Center.X, ellipse.Center.Y, ellipse.MajorRadius, ellipse.MinorRadius, ellipse.StartAngle, ellipse.EndAngle, ellipse.MajorAxis.X, ellipse.MajorAxis.Y);
            }
            foreach (DwgPoint simplePoint in simplePoints)
            {
                shapeFiles.Vertices.Add(simplePoint.X, simplePoint.Y);
            }
        }

        /// <summary>
        /// 添加dwg 曲线
        /// </summary>
        /// <param name="shapeFiles"></param>
        /// <param name="spline"></param>
        public static void AddDwgSpline(ShapeFile shapeFiles, Spline spline)
        {
            if (shapeFiles == null || spline == null)
            {
                return;
            }
            List<DwgPoint> simplePoints;
            simplePoints = GeometryUtils.CalcuteSplinePoints();
            foreach (DwgPoint simplePoint in simplePoints)
            {
                shapeFiles.Vertices.Add(simplePoint.X, simplePoint.Y);
            }
        }

        /// <summary>
        /// 获取shp字段的属性值
        /// 如果有返回
        /// 如果没有返回空字符串
        /// </summary>
        /// <param name="shapeFiles"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public static string TryGetString(ShapeFile shapeFiles, string name)
        {
            string type = "";
            ArcShapeFile.Field shapeField = shapeFiles.Fields[name];
            if (shapeField != null)
            {
                object value = shapeField.Value;
                if (value != null)
                {
                    type = value.ToString();
                }
            }
            return type;
        }

        /// <summary>
        /// 获取shp字段的属性值
        /// 如果有返回
        /// </summary>
        /// <param name="shapeFiles"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public static double TryGetDouble(ShapeFile shapeFiles, string name, double defaultValue)
        {
            double outValue = defaultValue;
            ArcShapeFile.Field shapeField = shapeFiles.Fields[name];
            if (shapeField != null)
            {
                object value = shapeField.Value;
                if (value != null)
                {
                    if (!double.TryParse(value.ToString(), out outValue))
                    {
                        outValue = defaultValue;
                    }
                }
            }
            return outValue;
        }

        public static int TryGetInteger(ShapeFile shapeFiles, string name, int defaultValue = 0)
        {
            int outValue = defaultValue;
            ArcShapeFile.Field shapeField = shapeFiles.Fields[name];
            if (shapeField != null)
            {
                object value = shapeField.Value;
                if (value != null)
                {
                    if (!int.TryParse(value.ToString(), out outValue))
                    {
                        outValue = defaultValue;
                    }
                }
            }
            return outValue;
        }

    }
}
